package com.ljx.rpc.core.transport.socket.server;

import com.ljx.rpc.core.handler.RequestHandler;
import com.ljx.rpc.core.domain.dto.RpcRequest;
import com.ljx.rpc.core.exception.RpcException;
import com.ljx.rpc.core.transport.RpcServer;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: LiJunXi
 * @Description:
 * @Date: 2024-10-07  19:43
 */
public class SocketServer implements RpcServer {

    private String host;
    private Integer port;

    private ExecutorService threadPool;
    private RequestHandler requestHandler;

    public SocketServer(String host, Integer port) {
        this.host = host;
        this.port = port;
        this.threadPool = new ThreadPoolExecutor(10, 50, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(100));
        this.requestHandler = new RequestHandler();
    }

    @Override
    public void start() {
        try {
            ServerSocket serverSocket = new ServerSocket();
            serverSocket.bind(new InetSocketAddress(host, port));
            System.out.println("----------》服务启动");
            Socket socket;
            while ((socket = serverSocket.accept()) != null) {
                Socket socketTmp = socket;
                threadPool.execute(() -> tryToHandleSocket(socketTmp));
            }

        } catch (IOException e) {
            throw new RpcException(e.getMessage());
        }

    }

    private void tryToHandleSocket(Socket socket) {
        try {
            ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
            RpcRequest rpcRequest = (RpcRequest) inputStream.readObject();
            Object result = requestHandler.handle(rpcRequest);
            outputStream.writeObject(result);
            outputStream.flush();
        } catch (Exception e) {
            throw new RpcException(e.getMessage());
        }

    }
}
